package oop.core.parsers;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import oop.core.entity.Occupation;
import oop.core.entity.Stats;
import oop.core.skill.*;

/**
 * parses an avatars Occupation into a string format we were planning on using to save and load 
 * avatar data 
 * @author srhinson
 *
 */

public class OccupationParser {
	static String del = "O~";
	static String specdel = "~~~";
	static String isdel = "IS~";
	
	public static String parseOut(Occupation occ){
		String data = "";
		data=data.concat(occ.getName()+del);
		//THIS IS TERRIBLE RTTI. VERY STRUCTURE DEPENDENT.  HACKED TOGETHER IN THE 11TH HOUR SO TO SPEAK. PLEASE BE MERCIFULL.
		// loops through interactive skill list.  Type field is first so I can predict what values follow.
		//Interactive Skill fields separated by isdel
		//Loop iterations represent one InteractiveSkill
		//InteractiveSkills separated by ~~~
		if(occ.getInteractiveSkill()!=null){
		for(InteractiveSkill i : occ.getInteractiveSkill()){
			if(i instanceof Enchantment){
				data=data.concat("ENCHANTMENT");
			}
			if(i instanceof PickPocket){
				data=data.concat("POCKET");
			}
			if(i instanceof Sleep){
				data=data.concat("SLEEP"+isdel);
				data=data.concat(Integer.toString(((Sleep)i).getDelayDuration()));
			}
			data=data.concat(isdel+i.getName());
			data=data.concat(isdel+i.getSkillLevel());
			data=data.concat(specdel);
		}
		}
		data=data.concat(del);
		
		
		//Same Schtick as above, but for passive skills.
		if(occ.getPassiveSkill()!=null){
		for(PassiveSkill p : occ.getPassiveSkill()){
			data=data.concat(p.getName()+isdel);
			data=data.concat(Integer.toString(p.getSkillLevel()));
			data=data.concat(specdel);
		}
		}
		data=data.concat(del);
		
		if(occ.getActiveSkill()!=null){
		for(ActiveSkill a:occ.getActiveSkill()){
			if(a==null){
				break;
			}
			if (a instanceof Cone){
				data=data.concat("CONE"+isdel);
				data=data.concat(Boolean.toString(((Cone)a).isRadial()));
			}
			if (a instanceof Radial){
				data=data.concat("RADIAL");
			}
			data=data.concat(isdel+a.getName());
			data=data.concat(isdel+a.getSkillLevel());
			data=data.concat(isdel+a.getLifeTime());
			data=data.concat(isdel+a.getHitCount());
			data=data.concat(isdel+a.getEffect());
			data=data.concat(isdel+a.getImage());
			data=data.concat(isdel+a.getPropogationDelay());
			data=data.concat(isdel+a.getRange()+isdel);
			if(a.getSkillsThatAffectMe()!=null){
			for(String s : a.getSkillsThatAffectMe()){
				data=data.concat(s+specdel);
			}
			}
			data=data.concat(isdel);
			if(a.getWeaponType()!=null){
			for(String ss : a.getWeaponType()){
				data=data.concat(ss+specdel);
			}
			}
		}
		}
		data=data.concat(del);
		data=data.concat(StatsParser.parseOut(occ.getLevelUpStats()));
		return data;
	}
	
	public static Occupation parseIn(String data){
		Scanner scanner = new Scanner(data);
		scanner.useDelimiter(del);
		String name=scanner.next();
		List<InteractiveSkill> iSkills = interactiveHelper(scanner.next());
		List<PassiveSkill> pSkills = passiveHelper(scanner.next());
		List<ActiveSkill> aSkills = activeHelper(scanner.next());
		Stats stats = StatsParser.parseIn(scanner.next());
		
		return new Occupation(name, iSkills, pSkills, aSkills, stats);
		
	}
	
	private static List<String> stringHelper(String data){
		Scanner scanner = new Scanner(data);
		scanner.useDelimiter(specdel);
		List<String> strings = new ArrayList<String>();
		while(scanner.hasNext()){
			strings.add(scanner.next());
		}
		return strings;
	}
	
	private static List<ActiveSkill> activeHelper(String data){
		Scanner scanner = new Scanner(data);
		scanner.useDelimiter(specdel);
		List<ActiveSkill> skills = new ArrayList<ActiveSkill>();
		while(scanner.hasNext()){
			skills.add(activeParse(scanner.next()));
		}
		return skills;
	}
	
	private static ActiveSkill activeParse(String data){
		Scanner scanner = new Scanner(data);
		scanner.useDelimiter(isdel);
		String type = scanner.next();
		if(type=="CONE"){
			return new Cone(Boolean.parseBoolean(scanner.next()), scanner.next(), Integer.parseInt(scanner.next()), Integer.parseInt(scanner.next()), Integer.parseInt(scanner.next()), Integer.parseInt(scanner.next()), scanner.next(), Integer.parseInt(scanner.next()), Integer.parseInt(scanner.next()), stringHelper(scanner.next()), stringHelper(scanner.next()));
		}
		if(type=="RADIAL"){
			return new Radial(scanner.next(), Integer.parseInt(scanner.next()), Integer.parseInt(scanner.next()), Integer.parseInt(scanner.next()), Integer.parseInt(scanner.next()), scanner.next(), Integer.parseInt(scanner.next()), Integer.parseInt(scanner.next()), stringHelper(scanner.next()), stringHelper(scanner.next()));
		}
		return null;		
	}
	
	private static List<PassiveSkill> passiveHelper(String data){
		Scanner scanner = new Scanner(data);
		scanner.useDelimiter(specdel);
		List<PassiveSkill> skills = new ArrayList<PassiveSkill>();
		while(scanner.hasNext()){
			skills.add(passiveParse(scanner.next()));
		}
		return skills;
	}
	
	private static PassiveSkill passiveParse(String data){
		Scanner scanner = new Scanner(data);
		scanner.useDelimiter(isdel);
		String name = scanner.next();
		int level = Integer.parseInt(scanner.next());
		return new PassiveSkill(name, level);
	}
	
	private static List<InteractiveSkill> interactiveHelper(String data){
		Scanner scanner = new Scanner(data);
		scanner.useDelimiter(specdel);
		List<InteractiveSkill> skills = new ArrayList<InteractiveSkill>();
		while(scanner.hasNext()){
			skills.add(interactiveParse(scanner.next()));
		}
		return skills;
	}
	
	private static InteractiveSkill interactiveParse(String data){
		Scanner scanner = new Scanner(data);
		scanner.useDelimiter(isdel);
		String type = scanner.next();
		if (type == "ENCHANTMENT"){
			return new Enchantment(scanner.next(), Integer.parseInt(scanner.next()));
		}
		if (type == "POCKET"){
			return new PickPocket(scanner.next(), Integer.parseInt(scanner.next()));
		}
		if (type == "SLEEP"){
			return new Sleep(Integer.parseInt(scanner.next()), scanner.next(), Integer.parseInt(scanner.next()));
		}
		return new Enchantment("filler", 0);
	}
}
